package com.tools.properties;

import com.google.common.base.Preconditions;
import org.apache.commons.lang3.StringUtils;
import org.yaml.snakeyaml.Yaml;

import java.io.*;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Yaml2PropertiesConvertor
 *
 * @author nanxin.chen
 * @since 2017/12/3
 */
public class Yaml2PropertiesConvertor {

    public static final String DIR_PATH = Yaml2PropertiesConvertor.class.getClassLoader().getResource("").getPath() + File.separator + "file";

    public void convert(File yamlFile, File propertiesFile) throws IOException {
        Map<String, Object> yaml = loadYaml(yamlFile);
        LinkedHashMap<String, Object> properties = map2properties(yaml);
        writeProperties(properties, propertiesFile);
    }

    private Map<String, Object> loadYaml(File yamlFile) throws FileNotFoundException {
        Yaml yaml = new Yaml();
        Map<String, Object> result = (Map<String, Object>) yaml.load(new FileInputStream(yamlFile));
        return result;
    }

    private LinkedHashMap<String, Object> map2properties(Map<String, Object> yaml) {
        Preconditions.checkArgument(yaml != null && yaml.size() > 0, "yaml 文件内容为空");
        LinkedHashMap<String, Object> properties = new LinkedHashMap<>(yaml.size() * 4);
        parser("", yaml, properties);
        return properties;
    }

    private void parser(String prefix, Object yaml, Map<String, Object> result) {
        Preconditions.checkArgument(yaml != null, "parser get null yaml, prefix:%s", prefix);
        if (yaml instanceof Map) {
            Map<String, Object> mapYaml = (Map<String, Object>) yaml;
            for (Map.Entry<String, Object> entry : mapYaml.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();
                String subPreFix = StringUtils.isBlank(prefix)
                        ? "" + key
                        : prefix + "." + key;
                if (value instanceof Map) {
                    parser(subPreFix, value, result);
                } else if (value instanceof List) {
                    parser(subPreFix, value, result);
                } else {
                    result.put(subPreFix, value);
                }
            }
        } else if (yaml instanceof List) {
            List<Object> listYaml = (List<Object>) yaml;
            for (int i = 0; i < listYaml.size(); i++) {
                Object value = listYaml.get(i);
                String subPreFix = StringUtils.isBlank(prefix)
                        ? "[" + i + "]"
                        : String.format("%s.[%s]", prefix, i);

                if (value instanceof Map || value instanceof List) {
                    parser(subPreFix, value, result);
                } else {
                    result.put(subPreFix, value);
                }
            }
        }
    }

    private void writeProperties(LinkedHashMap<String, Object> properties, File propertiesFile) throws IOException {
        if (!propertiesFile.exists()) {
            propertiesFile.createNewFile();
        }
        BufferedWriter bw = new BufferedWriter(new FileWriter(propertiesFile));
        for (Map.Entry<String, Object> entry : properties.entrySet()) {
            bw.write(entry.getKey() + " = " + entry.getValue());
            bw.newLine();
        }
        bw.close();
    }


    /**
     * for test
     *
     * @param args
     * @throws IOException
     */
    public static void main(String[] args) throws IOException {
        Yaml2PropertiesConvertor convertor = new Yaml2PropertiesConvertor();
//        convertor.convert(new File(DIR_PATH, "application.yml"), new File(DIR_PATH, "application.properties"));
        File dir = new File(DIR_PATH);
        File[] files = dir.listFiles(subFile -> {
            if (subFile.isFile() && subFile.getName().endsWith(".yml"))
                return true;
            else return false;
        });

        for (File file : files) {
            String fName = file.getName();
            String newName = fName.substring(0, fName.indexOf(".yml")) + ".properties";
            convertor.convert(file, new File(DIR_PATH, newName));
        }
    }

}
